package org.quickserver.util;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;











public class FileChangeMonitor
  implements Runnable
{
  private static final Logger logger = Logger.getLogger(FileChangeMonitor.class.getName());
  private static int sleepInterval = 15000;
  
  private static Map map = new ConcurrentHashMap<Object, Object>();
  private static Map lastModified = new ConcurrentHashMap<Object, Object>();
  private static volatile boolean flag;
  private static volatile Thread thread = null;
  private static FileChangeMonitor fcm = new FileChangeMonitor();

  
  public static synchronized boolean addListener(String file, FileChangeListener fcl) {
    if (file == null) return false; 
    File myFile = new File(file);
    if (!myFile.canRead()) return false;
    
    List<FileChangeListener> list = (List)map.get(file);
    if (list == null) {
      list = new ArrayList();
      map.put(file, list);
    } 
    return list.add(fcl);
  }
  
  public static synchronized boolean removeListener(String file, FileChangeListener fcl) {
    if (file == null) return false; 
    File myFile = new File(file);
    if (!myFile.canRead()) return false;
    
    List list = (List)map.get(file);
    if (list == null) {
      list = new ArrayList();
      map.put(file, list);
    } 
    return list.remove(fcl);
  }
  
  public static void startMonitoring() {
    if (flag)
      return; 
    flag = true;
    if (thread != null) {
      thread.interrupt();
      thread = null;
    } 
    thread = new Thread(fcm);
    thread.setPriority(1);
    thread.setDaemon(true);
    thread.start();
  }
  
  public static void stopMonitoring() {
    if (!flag)
      return; 
    flag = false;
    if (thread != null) {
      thread.interrupt();
    }
    thread = null;
  }
  
  public void run() {
    logger.info("Starting..");
    Iterator<String> iterator = null;
    String key = null;
    File file = null;
    String lastModifiedTimeOld = null;
    String lastModifiedTimeNew = null;
    FileChangeListener fcl = null;
    List<FileChangeListener> fclList = null;
    while (flag) {
      Set set = map.keySet();
      iterator = set.iterator();
      while (flag && iterator.hasNext()) {
        try {
          key = iterator.next();
          file = new File(key);
          long l = file.lastModified();
          
          lastModifiedTimeOld = (String)lastModified.get(key);
          if (lastModifiedTimeOld == null) {
            lastModified.put(key, l);
            continue;
          } 
          if (!lastModifiedTimeOld.equals(l)) {
            lastModified.put(key, l);
            fclList = (List)map.get(key);
            for (int i = 0; i < fclList.size(); i++) {
              fcl = fclList.get(i);
              fcl.changed();
            } 
          } 
        } catch (Exception e) {
          logger.log(Level.WARNING, "ERROR: " + e, e);
        } 
        
        try {
          Thread.sleep(sleepInterval);
        } catch (Exception e) {
          logger.log(Level.WARNING, "ERROR: " + e, e);
          break;
        } 
      } 
    } 
    logger.info("Stopped.");
  }
  
  public static void main(String[] args) throws Exception {
    FileChangeListener fcl = new FileChangeListener() {
        public void changed() {
          System.out.println("File changed: " + new Date());
        }
      };

    
    addListener("test.txt", fcl);
    startMonitoring();
  }
  
  static  {
    startMonitoring();
  }
}
